using System;
using System.Diagnostics;
using UnityEngine;
using UnityEditor;
using System.IO;
using XYTerrain.Runtime;
using Debug = UnityEngine.Debug;

namespace  XYTerrain.Editor
{

    public class MeshTerrianSoundData
    {
        public GameObject go;
        public Bounds bounds;
        public Texture2D tex;
        public int[] result;
    }

    /// <summary>
    ///  暂时只想到需要保存TerrainLayer数据
    /// </summary>
    
    
    public class MeshTerrainSoundBakeTool
    {


        
        
        
        /// <summary>
        /// 获取俯视控制图
        /// </summary>
        [MenuItem("GameObject/GetViewTex",priority =  1)]
        public static Texture2D GetPreviewCtlTex( MeshTerrianSoundData data,bool debug = false)
        {

            int layer = 8; // 幸运layer8
            var terrainMesh = data.go;
            
            var root = GameObject.Instantiate(terrainMesh);
            root.gameObject.layer = layer;
            var renderer = root.GetComponent<Renderer>();
            if (renderer == null)
            {
                Debug.LogError("没渲染组件");
                GameObject.DestroyImmediate(root);
                return null;
            }

            // TODO  有可能会改为当前物体下的所有子物体进行替换？  
            
            var ctlTex = renderer.sharedMaterial.GetTexture("_Control");
            var mat = new Material(Shader.Find("Hiddent/MeshTerrianBake"));
            mat.SetTexture("_Control",ctlTex);
            root.GetComponent<Renderer>().material = mat;
            var bounds = root.GetComponent<Renderer>().bounds;
            // ------------ RT设置-----------------
            
            var resolution = Mathf.CeilToInt(Mathf.Max(bounds.size.x, bounds.size.z));
            var rt = RenderTexture.GetTemporary(resolution,resolution,0);

            // - -  - - - - - -镜头设置
            var camGo = new GameObject("PreViewCam");
            var cam = camGo.AddComponent<Camera>();
            cam.rect = new Rect(0, 0, 1, 1);
            cam.orthographic = true;
            cam.transform.eulerAngles = new Vector3(90, 0, 0);
            cam.transform.position = bounds.center +  Vector3.up*bounds.size.y+Vector3.up*100;
            cam.nearClipPlane = 0.5f;
            cam.farClipPlane = cam.transform.position.y + 1000.0f;
            cam.orthographicSize = Mathf.Max((bounds.max.x-bounds.min.x)/2f,(bounds.max.z-bounds.min.z)/2);
            cam.clearFlags = CameraClearFlags.SolidColor;
            cam.backgroundColor = Color.black;
            cam.targetTexture = rt;
            cam.cullingMask = 1<<layer;
            //-----------------------------------
            
            RenderTexture.active = rt;
            Selection.activeObject = camGo;
            
            cam.Render();
            cam.targetTexture = null;
            
            data.tex  = new Texture2D(rt.width,rt.height);
            var mainTex = data.tex;
            mainTex.ReadPixels(new Rect(0,0,rt.width,rt.height),0,0);
            mainTex.Apply();
            
            RenderTexture.active = null; 
            RenderTexture.ReleaseTemporary(rt);
            Selection.activeObject = null;
            GameObject.DestroyImmediate(camGo);
            GameObject.DestroyImmediate(root);
           
            // 调试输出贴图
            if (debug)
            {
                string savePath = Application.dataPath;
                System.IO.FileStream main_file = File.Open(savePath + "/soundBeakTex.png", FileMode.OpenOrCreate);
                var main_TexBytes = mainTex.EncodeToPNG();
                main_file.Write(main_TexBytes,0,main_TexBytes.Length);
                main_file.Close();    
                Debug.Log("贴图输出成功");
                AssetDatabase.SaveAssets();
                AssetDatabase.Refresh();

            }

            data.bounds = bounds;
            // data.tex = mainTex; 
            return mainTex;

        }



        public static uint[,] GetSoundData(MeshTerrianSoundData data,PaintTerrainData paintData,System.Func<TerrainLayer,uint> GetSoundId)
        {
            int width = Mathf.CeilToInt( data.bounds.size.x);
            Debug.Log(data.bounds.size);
            int height = Mathf.CeilToInt( data.bounds.size.z);
            uint[,] soundData = new uint[width,height];


            
            
            int index  = 0;
            for (int x  = 0; x  < width; x ++)
            {
                for (int y = 0; y < height; y++)
                {
                    index = x + y * height;
                    int maxIndex = 0 ;
                    float maxColor = 0;
                    var col = data.tex.GetPixel(x, y);
                    
                     
                    // 黑色意味着无音效的空地 
                    if(col==Color.black)
                    {
                        soundData[x, y] = 0;
                    }
                    else
                    {
                        for (int num = 0; num < paintData.Layers.Count; num++)
                        {
                           var currentCol =  GetColor(col, num);
                           if (currentCol > maxColor)
                           {
                               maxIndex = num;
                               maxColor = currentCol;
                           }
                        }    
                        soundData[x, y] =  GetSoundId(paintData.Layers[maxIndex]);
                    }
                    
                } 
            }
            
            return soundData;
        }

        public static float GetColor(Color col,int index)
        {
            if (index == 0) return col.r;
            if (index == 1) return col.g;
            if (index == 2) return col.b;
            if (index == 3) return col.a;
            else return col.r;
        }



        /// <summary>
        /// 支持一键烘焙多个子地块音效 
        /// </summary>
        public void BeakSingle()
        {
            
        }
        
        
        /// <summary>
        /// 循环所有子物体并且更换材质球？ 
        /// 获取所有渲染的物体  TODO 后面再支持 ，正确用法应该只有一个大物体作为地表使用这个功能罢了。
        /// </summary>
        /// <returns></returns>
        // private List<Renderer> AllRenderObject()
        // {
        //     
        // }
        
        
    }
}


    